package ai.people.platform.archives.aspect;

import ai.people.core.security.support.RequestHolderUtil;
import ai.people.netmon.framework.businessenum.information.InformationSearchBehaviorEnum;
import ai.people.netmon.framework.domain.archives.annotation.BehaviorLog;
import ai.people.netmon.framework.domain.archives.entity.InformationAccountBehavior;
import ai.people.netmon.framework.domain.archives.entity.InformationBehavior;
import ai.people.netmon.framework.domain.archives.request.InformationSearchRequest;
import ai.people.netmon.framework.domain.archives.vo.InformationDataBasicFieldVO;
import ai.people.netmon.framework.domain.archives.vo.InformationDetailRespVO;
import ai.people.netmon.framework.exception.enums.AuthExceptionEnum;
import ai.people.netmon.framework.exception.enums.InformationSearchExceptionEnum;
import ai.people.netmon.framework.exception.type.BusinessException;
import ai.people.platform.archives.service.InformationAccountBehaviorService;
import ai.people.platform.archives.service.InformationAccountService;
import ai.people.platform.archives.service.InformationBehaviorService;
import ai.people.platform.information.context.InformationServiceContext;
import ai.people.platform.information.properties.DataSourceProperties;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 行为日志切面
 *
 * @author 李冠男
 * @date 2022/06/07
 */
@Slf4j
@Aspect
@Component
public class BehaviorLogAspect {

    @Autowired
    private InformationBehaviorService informationBehaviorService;

    @Autowired
    private InformationAccountService informationAccountService;

    @Autowired
    private InformationAccountBehaviorService informationAccountBehaviorService;

    @Autowired
    private InformationServiceContext informationServiceContext;


    @Pointcut("@annotation(ai.people.netmon.framework.domain.archives.annotation.BehaviorLog)")
    private void cut() {
    }

    @Around("cut() && @annotation(behaviorLog)")
    public Object advice(ProceedingJoinPoint joinPoint, BehaviorLog behaviorLog) throws Throwable {
        Object object = null;

        //获取行为信息
        if(behaviorLog != null && behaviorLog.behaviorCode() != null){
            QueryWrapper<InformationBehavior> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("code", behaviorLog.behaviorCode().getCode()).eq("is_delete", 0).last("LIMIT 1");
            InformationBehavior behavior = informationBehaviorService.getOne(queryWrapper, false);
            if(behavior == null){
                throw new BusinessException(InformationSearchExceptionEnum.ILLEGAL_BEHAVIOR);
            }

            //获取登录用户
            Long userId = RequestHolderUtil.getUserId();
            if(userId == null){
                throw new BusinessException(AuthExceptionEnum.UNAUTHORIZED_ACCESS);
            }
            log.info("信息查询行为日志拦截，登录用户user_id：【{}】",userId);

            //执行具体操作
            try {
                object = joinPoint.proceed();
            }catch (Exception e) {
                log.error("第三方信息查询行为执行失败");
                e.printStackTrace();
                throw new BusinessException(InformationSearchExceptionEnum.INFORMATION_SEARCH_ERROR);
            }

            //行为记录
            saveBehaviorLog(joinPoint, object, behavior, userId);
        }
        return object;
    }

    /**
     * 保存行为日志
     *
     * @param joinPoint 连接点
     * @param object    对象
     * @param behavior  行为
     * @param userId    用户id
     */
    private void saveBehaviorLog(ProceedingJoinPoint joinPoint, Object object, InformationBehavior behavior, Long userId) {
        if(object != null){
            HashMap<String, String> map = Maps.newHashMap();
            String dataId = null;
            String dataSource = null;
            String extJson = "";
            if(InformationSearchBehaviorEnum.search.getCode() == behavior.getCode()){
                InformationSearchRequest arg = (InformationSearchRequest) joinPoint.getArgs()[0];
                if(StringUtils.isNotBlank(arg.getSearchKeywords())){
                    map.put("keyword", arg.getSearchKeywords());
                }
            }else if(InformationSearchBehaviorEnum.detail.getCode() == behavior.getCode()){
                InformationDetailRespVO respVo= (InformationDetailRespVO) object;
                InformationDataBasicFieldVO basicField = respVo.getBasicField();
                Map<String, Object> showFields = respVo.getShowFields();
                if(basicField != null && showFields != null){
                    dataId = basicField.getDataId();
                    dataSource = basicField.getDataSource();
                    extJson = JSONObject.toJSONString(respVo);
                    map.put("keyword", getDetailKeyword(showFields));
                    map.put("dataId", basicField.getDataId());
                    map.put("dataSource", basicField.getDataSource() + "");
                    HashMap<String, Object> listShowFields = Maps.newLinkedHashMap();
                    DataSourceProperties dataSourceProperties = informationServiceContext.getEnableServerConfig(dataSource);
                    List<String> fieldShowOrder = dataSourceProperties.getSearch().getFieldShowOrder();
                    if(!CollectionUtils.isEmpty(fieldShowOrder)){
                        fieldShowOrder.forEach(o->{
                            listShowFields.put(o, showFields.get(o));
                        });
                    }
                    map.put("listShowFields", JSON.toJSONString(listShowFields));
                }
            }
            if(!map.isEmpty()){
                //消费积分
                int i = informationAccountService.payScore(userId, behavior.getId(), dataId, dataSource, extJson);
                if(i == 0){
                    InformationAccountBehavior accountBehavior = new InformationAccountBehavior();
                    accountBehavior.setUserId(userId);
                    accountBehavior.setBehaviorId(behavior.getId());
                    accountBehavior.setCreateTime(new Date());
                    accountBehavior.setTs(new Date());
                    accountBehavior.setIsDelete(0);
                    accountBehavior.setScore(behavior.getScore());
                    accountBehavior.setExtJson(JSON.toJSONString(map));
                    informationAccountBehaviorService.save(accountBehavior);
                }
            }
        }
    }

    private String getDetailKeyword(Map<String, Object> showFields) {
        if(StringUtils.isNotBlank((String) showFields.get("姓名"))){
            return "姓名：" + showFields.get("姓名");
        } else if(StringUtils.isNotBlank((String) showFields.get("邮箱"))){
            return "邮箱：" + showFields.get("邮箱");
        } else if(StringUtils.isNotBlank((String) showFields.get("手机号"))){
            return "手机号：" + showFields.get("手机号");
        } else if(StringUtils.isNotBlank((String) showFields.get("id"))){
            return "id：" + showFields.get("id");
        } else if(StringUtils.isNotBlank((String) showFields.get("uid"))){
            return "uid：" + showFields.get("uid");
        } else if(StringUtils.isNotBlank((String) showFields.get("dataId"))){
            return "dataId：" + showFields.get("dataId");
        }
        return "";
    }
}
